package basisService

import (
	"bytes"
	"encoding/json"
	"github.com/Sir-yuChen/funAnalyse/global"
	"github.com/Sir-yuChen/funAnalyse/model"
	"github.com/Sir-yuChen/funAnalyse/model/common/ApiReturn"
	"github.com/Sir-yuChen/funAnalyse/service/commonService"
	"github.com/Sir-yuChen/funAnalyse/utils"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type StockMenuService struct{}

func NewStockMenuService() *StockMenuService {
	return &StockMenuService{}
}

//GetStockMenu 多条件查询
func (u *StockMenuService) GetStockMenu(req *model.StockMenuModel) (a ApiReturn.ApiReturnCode) {
	var mo []model.StockMenuModel
	sql := ""
	obj := model.NewStockMenuModel()
	tableName := obj.TableName()
	sqlCondition := utils.ReflectHandleStuct(req)
	if sqlCondition != "" {
		sql = `select * from ` + tableName + ` where ` + sqlCondition
	} else {
		sql = `select * from ` + tableName + ` order by id desc  limit 100 `
	}
	err := global.GVA_DB.Raw(sql).Scan(&mo).Error
	if err != nil {
		global.GVA_LOG.Error("basis Get异常", zap.Any("req", req), zap.Any("sql", sql), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	s := ApiReturn.OK
	s.Data = mo
	return s
}

//InsertStockMenu
func (u *StockMenuService) InsertStockMenu(req *model.StockMenuModel, c *gin.Context) (a ApiReturn.ApiReturnCode) {
	//校验资源是否存在
	var resourceReq model.StockApiResource
	resourceReq.Id = int32(req.MenuApiId)
	returnCode := NewCommonService().GetStockApiResource(&resourceReq)
	if returnCode.Code != ApiReturn.OK.Code || returnCode.Data == nil {
		global.GVA_LOG.Error("InsertStockMenu 校验资源不存在", zap.Any("request", req))
		return ApiReturn.ErrSystem
	}
	user, err := commonService.GetUserInfoByToken(c)
	if err != nil {
		global.GVA_LOG.Error("InsertStockMenu 获取当前操作用户信息异常", zap.Any("request", req))
		return ApiReturn.ErrSystem
	}
	//菜单名称不能相同  todo 空值处理
	var total int64
	if err = global.GVA_DB.Model(model.StockMenuModel{}).Where(" menu_name = ? ", req.MenuName).Count(&total).Error; err != nil {
		global.GVA_LOG.Error("InsertStockMenu 校验菜单名称异常", zap.Any("request", req))
		return ApiReturn.ErrSystem
	}
	if total > 0 {
		return ApiReturn.ExistingMenuName
	}
	req.CreateBy = user.CustomerName
	err = global.GVA_DB.Model(model.StockMenuModel{}).Create(&req).Error
	if err != nil {
		global.GVA_LOG.Error("InsertStockMenu insert异常", zap.Any("req", req), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	return ApiReturn.OK
}

//UpdateStockMenu 更新
func (u *StockMenuService) UpdateStockMenu(req *model.StockMenuModel) (a ApiReturn.ApiReturnCode) {
	if req.Id == 0 {
		return ApiReturn.ErrParam
	}
	err := global.GVA_DB.Model(req).Updates(req).Error
	if err != nil {
		global.GVA_LOG.Error("basis Update异常", zap.Any("req", req), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	return ApiReturn.OK
}

//DelStockMenu 根据ID删除
func (u *StockMenuService) DelStockMenu(req *model.StockMenuModel) (a ApiReturn.ApiReturnCode) {
	if req.Id == 0 {
		return ApiReturn.ErrParam
	}
	err := global.GVA_DB.Model(req).Where("id = ?", req.Id).Delete(model.StockMenuModel{}).Error
	if err != nil {
		global.GVA_LOG.Error("basis Del异常", zap.Any("req", req), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	return ApiReturn.OK
}

// GetStockMenuTree 菜单树
func (u *StockMenuService) GetStockMenuTree() (a ApiReturn.ApiReturnCode) {
	parentIds := []uint{0}
	trees, err := MenuTrees(parentIds, nil)
	if err != nil {
		a := ApiReturn.ErrSystem
		a.Msg = err.Error()
		return a
	}
	ok := ApiReturn.OK
	ok.Data = trees
	return ok
}

func MenuTrees(parentIds []uint, result []map[string]interface{}) ([]map[string]interface{}, error) {
	var tempParntids []uint
	for _, id := range parentIds {
		stockMenuModels, err := Getparents(id)
		if err != nil {
			global.GVA_LOG.Error("GetStockMenuTree 父菜单异常", zap.Error(err))
			return nil, err
		}
		if len(stockMenuModels) <= 0 {
			global.GVA_LOG.Warn("GetStockMenuTree 未查询到对应的父菜单", zap.Any("parentId", parentIds))
			continue
		}
		for _, menu := range stockMenuModels {
			parentIds = []uint{}
			j := JSONMethod(menu)
			if menu.MenuApiId != 0 {
				apiPath := ""
				//存在资源查询资源
				if err := global.GVA_DB.Model(model.StockApiResource{}).Select("api_path").Where(" id = ? ", menu.MenuApiId).First(&apiPath).Error; err != nil {
					global.GVA_LOG.Error("GetStockMenuTree 获取菜单对应的资源异常", zap.Error(err))
					return nil, err
				}
				j["apiPath"] = apiPath
			}
			//todo 存在图片查询icon
			result, err = ConfirmLocation(result, j)
			if err != nil {
				global.GVA_LOG.Error("GetStockMenuTree 确认菜单位置", zap.Error(err))
				return nil, err
			}
			tempParntids = append(tempParntids, menu.Id)
		}
	}
	if len(tempParntids) > 0 && tempParntids != nil {
		MenuTrees(tempParntids, result)
	}
	return result, nil
}

func Getparents(parentId uint) ([]model.StockMenuModel, error) {
	var pmenus []model.StockMenuModel
	if err := global.GVA_DB.Model(model.StockMenuModel{}).Where(" parent_id = ? AND status = ? ", parentId, "Y").Order(" menu_order asc ").Find(&pmenus).Error; err != nil {
		global.GVA_LOG.Error("Getparents 父菜单异常", zap.Error(err))
		return nil, err
	}
	return pmenus, nil
}
func ConfirmLocation(result []map[string]interface{}, menu map[string]interface{}) ([]map[string]interface{}, error) {
	var temp = []map[string]interface{}{}
	menuParentId := menu["parentId"]
	if len(result) == 0 && result == nil {
		result = append(result, menu)
		return result, nil
	}
	for i, v := range result {
		id := v["id"]
		if id == menuParentId {
			if c, ok := v["child"]; ok { //key是否存在
				cv, t := c.([]map[string]interface{})
				if t {
					v["child"] = append(cv, menu)
					return result, nil
				}
			} else {
				v["child"] = append(temp, menu)
				return result, nil
			}
		} else {
			if c, ok := v["child"]; ok { //key是否存在
				cv, _ := c.([]map[string]interface{})
				//使用递归
				cv, err := ConfirmLocation(cv, menu)
				if err != nil {
					global.GVA_LOG.Error("确认子菜单位置递归异常", zap.Error(err))
					return nil, err
				}
			} else {
				if len(result)-1 == i {
					result = append(result, menu)
					return result, nil
				}
			}

		}
	}
	return result, nil
}

// JSONMethod struct转map
func JSONMethod(content interface{}) map[string]interface{} {
	var m map[string]interface{}
	if marshalContent, err := json.Marshal(content); err != nil {
		global.GVA_LOG.Error("数据转换异常", zap.Error(err))
	} else {
		d := json.NewDecoder(bytes.NewReader(marshalContent))
		d.UseNumber() // 设置将float64转为一个number
		if err := d.Decode(&m); err != nil {
			global.GVA_LOG.Error("数据转换异常", zap.Error(err))
		} else {
			for k, v := range m {
				m[k] = v
			}
		}
	}
	return m
}
